<?php
/**
 * RAI(Remote Access Interface) XmlRpc助手类
 *
 *
 * @author iwind <iwind.iwind@gmail.com>
 * @link http://www.4kiki.net/
 * @version $Id: XmlRpcHelper.php 312 2008-04-23 16:29:38Z iwind $
 * @package net.4kiki.rai.format.xmlrpc
 */

import("net.4kiki.rai.format.xmlrpc.decoder.*");
import("net.4kiki.rai.format.xmlrpc.encoder.*");

/**
 * XmlRpc助手类
 *
 * @version $Id: XmlRpcHelper.php 312 2008-04-23 16:29:38Z iwind $
 * @package net.4kiki.rai.format.xmlrpc
 * @since 0.0.3
 */
class XmlRpcHelper {
	/**
	 * 取得编码器
	 *
	 * @param mixed $phpVar PHP变量
	 * @param string $charset 字符集
	 * @return XmlRpcEncoder
	 */
	public static function getEncoder($phpVar, $charset) {
		$type = gettype($phpVar);
		switch ($type) {
			case "boolean":
				return new XmlRpcBooleanEncoder($phpVar, $charset);
			case "integer":
				return new XmlRpcIntEncoder($phpVar, $charset);
			case "string":
				return new XmlRpcStringEncoder($phpVar, $charset);
			case "double":
				return new XmlRpcDoubleEncoder($phpVar, $charset);
			case "array":
				if (self::isAssocArray($phpVar)) {
					return new XmlRpcStructEncoder($phpVar, $charset);
				}
				else {
					return new XmlRpcArrayEncoder($phpVar, $charset);
				}
			case "object":
				switch(get_class($phpVar)) {
					case "IBase64":
						return new XmlRpcBase64Encoder($phpVar->__toString(), $charset);
					case "IArrayList":
						return new XmlRpcArrayEncoder($phpVar->toArray(), $charset);
					case "IAssocMap":
						return new XmlRpcStructEncoder($phpVar->toArray(), $charset);
					default:
						return self::getEncoder(get_object_vars($phpVar), $charset);
				}
			case "NULL":
				return self::getEncoder("", $charset);
			default:
				return self::getEncoder("", $charset);
		}
	}
	
	/**
	 * 取得解码器
	 *
	 * @param string $rpcParamType XmlRpc参数类型
	 * @param string $xmlString XML字符串
	 * @param string $charset 字符集
	 * @return XmlRpcDecoder
	 */
	public static function getDecoder($rpcParamType, $xmlString, $charset) {
		switch ($rpcParamType) {
			case "boolean":
				return new XmlRpcBooleanDecoder($xmlString, $charset);
			case "i4":
				return new XmlRpcI4Decoder($xmlString, $charset);
			case "int":
				return new XmlRpcIntDecoder($xmlString, $charset);
			case "string":
				return new XmlRpcStringDecoder($xmlString, $charset);
			case "array":
				return new XmlRpcArrayDecoder($xmlString, $charset);
			case "struct":
				return new XmlRpcStructDecoder($xmlString, $charset);
			case "base64":
				return new XmlRpcBase64Decoder($xmlString, $charset);
			case "dateTime.iso8601":
				return new XmlRpcDatetTimeDecoder($xmlString, $charset);
			case "double":
				return new XmlRpcDoubleDecoder($xmlString, $charset);
		}
		throw new RaiException("unknown data type '{$rpcParamType}'");
	}
	
	/**
	 * 检查格式是否完整
	 *
	 * 返回处理后的结果
	 * 
	 * @param string $xmlString XML字符串
	 * @return string
	 */
	public static function checkXml($xmlString) {
		$xmlString = preg_replace_callback("/<value>((?!<[\.\w]+>).*)<\/value>/sU", array("self", "checkXmlCallback"), $xmlString);
		return $xmlString;
	}
	
	private static function checkXmlCallback($match) {
		return "<value><string>" . $match[1] . "</string></value>";
	}
	
	private static function isAssocArray($array) {
		$keys = array_keys($array);
		if ($keys === range(0, count($array) -1)) {
			return false;
		}
		return true;
	}
}

?>